package com.stox.repository.file;

import java.io.File;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.stox.manager.CountryManager;
import com.stox.manager.ExchangeManager;
import com.stox.manager.ScripManager;
import com.stox.model.Bar;
import com.stox.model.Country;
import com.stox.model.Exchange;
import com.stox.model.Scrip;
import com.stox.repository.BarRepository;

@Component
public class BarFileRepository extends AbstractFileRepository<Bar, String> implements BarRepository, InitializingBean {
	
	@Autowired
	private ScripManager scripManager;
	
	@Autowired
	private ExchangeManager exchangeManager;
	
	@Autowired
	private CountryManager countryManager;
	
	public void afterPropertiesSet() throws Exception {
		for(Country country : countryManager.findAll()){
			for(Exchange exchange : exchangeManager.findByCountryCode(country.getCode())){
				for(Scrip scrip : scripManager.findByExchangeCode(exchange.getCode())){
					try {
						cache(getFilePath(scrip.getCode()));
					}catch(FileNotFoundException e) {
						System.out.println("File not found for : "+scrip);
					}
				}
			}
		}
	}
	
	@Override
	protected String getFilePath(String scripCode) {
		Scrip scrip = scripManager.findOne(scripCode);
		if(null == scrip) return null;
		Exchange exchange = exchangeManager.findOne(scrip.getExchangeCode());
		if(null == exchange) return null;
		return getFilebasePath()+File.separator+
				exchange.getCountryCode().trim().toUpperCase()+File.separator+
				exchange.getCode().trim().toUpperCase()+File.separator+
				scrip.getCode().trim().toUpperCase()+".csv";
	}
	
	@Override
	protected Bar deserialize(String text, String scripCode) {
		return new Bar(scripCode, text);
	}
	
	public List<Bar> findByScripCode(String scripCode){
		final List<Bar> bars = new ArrayList<Bar>();
		iterate(new EntityIterator<Bar>(){
			public boolean shouldContinue(Bar entity) {
				bars.add(entity);
				return true;
			}
		}, scripCode);
		return bars;
	}

	public List<Bar> findByScripCode(String scripCode, final Date start){
		final List<Bar> bars = new ArrayList<Bar>();
		iterate(new EntityIterator<Bar>(){
			public boolean shouldContinue(Bar bar) {
				bars.add(bar);
				return (bar.getDate().after(start) || bar.getDate().equals(start));
			}
		}, scripCode);
		return bars;
	}
	
	public List<Bar> findByScripCode(String scripCode,final int count){
		final List<Bar> bars = new ArrayList<Bar>();
		iterate(new EntityIterator<Bar>(){
			private int subCount;
			public boolean shouldContinue(Bar bar) {
				bars.add(bar);
				return subCount <= count;
			}
		}, scripCode);
		return bars;
	}
	
	public List<Bar> findByScripCode(String scripCode, final Date start, final Date end) {
		final List<Bar> bars = new ArrayList<Bar>();
		iterate(new EntityIterator<Bar>(){
			public boolean shouldContinue(Bar bar) {
				if((bar.getDate().equals(start) || bar.getDate().after(start)) &&
						(bar.getDate().equals(end) || bar.getDate().before(end))){
					bars.add(bar);
				}
				return bar.getDate().before(start);
			}
		}, scripCode);
		return bars;
	}
	
	private int count;
	private void checkFlush(){
		count++;
		if(100000 <= count){
			flush();
			count = 0;
		}
	}
	
	public Bar save(Bar bar) {
		checkFlush();
		return super.save(bar, bar.getScripCode());
	}

	@Override
	protected String serialize(Bar bar) {
		return bar.toString();
	}

}
